﻿using RM.BasicLibrary.Cryptographys;
using RM.BasicLibrary.Exceptions;
using RM.BasicLibrary.Iocs;
using RM.BasicLibrary.Logs;
using RM.BasicLibrary.Models;
using RM.BasicLibrary.Models.Databases;
using RM.BasicLibrary.Models.Repositorys;
using System;
using System.Configuration;
using System.Data.Entity;

namespace RM.BasicLibrary
{
    /// <summary>
    /// 引导程序扩展方法
    /// </summary>
    public static partial class Extension
    {
        /// <summary>
        /// 设置异常过滤器
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="filter">异常过滤器</param>
        /// <returns></returns>
        public static Bootstraps SetFilter(this Bootstraps bootstraps, IFilter filter)
        {
            bootstraps.ExFilter = filter;
            return bootstraps;
        }
        /// <summary>
        /// 设置异常处理器
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="handler">异常处理器</param>
        /// <returns></returns>
        public static Bootstraps SetHandler(this Bootstraps bootstraps, IHandler handler)
        {
            bootstraps.ExHandler = handler;
            return bootstraps;
        }
        /// <summary>
        /// 设置数据转换处理器
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="dataConvert">数据转换实现的对象</param>
        /// <returns></returns>
        public static Bootstraps SetDataConvert(this Bootstraps bootstraps, IDataConvert dataConvert)
        {
            bootstraps.DataConvert = dataConvert;
            return bootstraps;
        }
        /// <summary>
        /// 设置sql生成处理器
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="sqlBuilder">sql生成自定义对象</param>
        /// <returns></returns>
        public static Bootstraps SetSqlBuilder(this Bootstraps bootstraps, ISqlBuilder sqlBuilder)
        {
            bootstraps.SqlBuilder = sqlBuilder;
            return bootstraps;
        }
        /// <summary>
        /// en-US \ zh-CN
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public static Bootstraps SetLanguage(this Bootstraps bootstraps, string language)
        {
            bootstraps.Resource.SetLanguage(language);
            return bootstraps;
        }
        public static Bootstraps SetLog(this Bootstraps bootstraps, IBaseLog baseLog)
        {
            bootstraps.Log = baseLog;
            return bootstraps;
        }
        /// <summary>
        /// 设置本地日志信息
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="logPath"></param>
        /// <param name="fileName"></param>
        /// <param name="log_pattern"></param>
        /// <returns></returns>
        public static Bootstraps SetLog(this Bootstraps bootstraps, string logPath, string fileName = "yyyy-MM-dd'.html'", string log_pattern = "<hr color=red />%date %level %c- %m%n <hr/>", string repositoryName = "LocalLog")
        {
            if (bootstraps.Log is BaseLog)
            {
                var log = (bootstraps.Log as BaseLog);
                log.SetLocalLog(logPath, fileName, log_pattern);
            }
            return bootstraps;
        }
        public static Bootstraps SetIoc(this Bootstraps bootstraps, IIocManager iocManager)
        {
            bootstraps.IocManager = iocManager;
            return bootstraps;
        }
        public static Bootstraps IocRegister<TInstance>(this Bootstraps bootstraps)
        {
            bootstraps.IocManager.Register<TInstance>();
            return bootstraps;
        }
        public static Bootstraps Register<TInterface, TInstance>(this Bootstraps bootstraps)
        {
            bootstraps.IocManager.Register<TInterface, TInstance>();
            return bootstraps;
        }
        public static Bootstraps Register<TInterface, TInstance>(this Bootstraps bootstraps, string instanceName)
        {
            bootstraps.IocManager.Register<TInterface, TInstance>(instanceName);
            return bootstraps;
        }
        public static Bootstraps Register<TInstance>(this Bootstraps bootstraps, TInstance instance) where TInstance : class
        {
            bootstraps.IocManager.Register(instance);
            return bootstraps;
        }
        /// <summary>
        /// 设置descrypt加密对象
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="crypt"></param>
        /// <returns></returns>
        public static Bootstraps SetDESCrypt(this Bootstraps bootstraps, ICrypt crypt)
        {
            bootstraps.DESCrypt = crypt;
            return bootstraps;
        }
        /// <summary>
        /// 设置对称加密的key 和 IV
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="key">加密密钥</param>
        /// <param name="iv">加密向量</param>
        /// <returns></returns>
        public static Bootstraps SetDESCryptKeyIv(this Bootstraps bootstraps, string key, string iv)
        {
            if (bootstraps.DESCrypt is DESCrypt)
                (bootstraps.DESCrypt as DESCrypt).SetDESCryptKeyIv(key, iv);
            return bootstraps;
        }
        /// <summary>
        /// 设置descrypt加密对象
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="crypt"></param>
        /// <returns></returns>
        public static Bootstraps SetRSACrypt(this Bootstraps bootstraps, ICrypt crypt)
        {
            bootstraps.RSACrypt = crypt;
            return bootstraps;
        }
        /// <summary>
        /// 设置公钥私钥地址
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="privateKeyPath"></param>
        /// <param name="publicKeyPath"></param>
        /// <returns></returns>
        public static Bootstraps SetKeyPath(this Bootstraps bootstraps, string privateKeyPath = "d:\\PrivateKey.xml", string publicKeyPath = "d:\\PublicKey.xml")
        {
            if (bootstraps.DESCrypt is RSACrypt)
                (bootstraps.DESCrypt as RSACrypt).SetKeyPath(privateKeyPath, publicKeyPath);
            return bootstraps;
        }
        /// <summary>
        ///  创建RSA公钥私钥
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="privateKeyPath"></param>
        /// <param name="publicKeyPath"></param>
        /// <returns></returns>
        public static Bootstraps CreateRSAKey(this Bootstraps bootstraps, string privateKeyPath = "d:\\PrivateKey.xml", string publicKeyPath = "d:\\PublicKey.xml")
        {
            if (bootstraps.DESCrypt is RSACrypt)
                (bootstraps.DESCrypt as RSACrypt).CreateRSAKey(privateKeyPath, publicKeyPath);
            return bootstraps;
        }
        /// <summary>
        /// 设置仓储
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="repository"></param>
        /// <returns></returns>
        public static Bootstraps SetRepository(this Bootstraps bootstraps, IRepository repository)
        {
            bootstraps.Repository = repository;
            return bootstraps;
        }
        /// <summary>
        ///  创建默认的仓储 root.ins.database 的数据库连接和模式
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <returns></returns>
        public static Bootstraps CreateRepository(this Bootstraps bootstraps, IDatabase database)
        {
            if (database.IsNull())
                bootstraps.Repository.Create(bootstraps.Database);
            else bootstraps.Repository.Create(database);
            return bootstraps;
        }


#if NET45 || NET46
        public static Bootstraps SetLog(this Bootstraps bootstraps, string connectionString, string commandText, DBType dBType)
        {
            if (bootstraps.Log is BaseLog)
            {
                var log = (bootstraps.Log as BaseLog);
                log.SetDBLog(connectionString, commandText, dBType);
            }
            return bootstraps;
        }
#endif
        /// <summary>
        /// 设置sql生成处理器
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="sqlHander">sql生成自定义对象</param>
        /// <returns></returns>
        public static Bootstraps SetDatabase(this Bootstraps bootstraps, IDatabase database)
        {
            bootstraps.Database = database;
            return bootstraps;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="connectionString">sql生成自定义对象,连接字符串为空，请将连接字符串的key配置为：ConnectionString</param>
        /// <param name="dBType"></param>
        /// <returns></returns>
        public static Bootstraps SetDatabase(this Bootstraps bootstraps, string connectionString = "")
        {
            bootstraps.Database.SetDatabase(connectionString);
            return bootstraps;
        }
        public static Bootstraps SetModels(this Bootstraps bootstraps, Action<DbModelBuilder> OnModelCreate)
        {
            bootstraps.Repository.SetModels(OnModelCreate);
            return bootstraps;
        }
        /// <summary>
        /// 创建数据库实例
        /// </summary>
        /// <param name="bootstraps"></param>
        /// <param name="connectionString">sql生成自定义对象,连接字符串为空，请将连接字符串的key配置为：ConnectionString</param>
        /// <param name="dBType">数据库操作类型</param>
        /// <returns></returns>
        public static Bootstraps SetDatabase(this Bootstraps bootstraps, DBType dBType = DBType.MSSQL, string connectionString = "")
        {
            if (connectionString.IsNull())
                Root.BasicIns.ExFilter.Execute(() => connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
            if (connectionString.IsNull())
                Root.BasicIns.ExFilter.Execute(() => connectionString = ConfigurationManager.AppSettings["ConnectionString"].ToString());
            switch (dBType)
            {
                case DBType.MSSQL:
                    bootstraps.Database = new MSDatabase();
                    break;
                case DBType.MYSQL:
                    bootstraps.Database = new MYSQLDatabase();
                    break;
                case DBType.ORACLE:
                    bootstraps.Database = new ORACLEDatabase();
                    break;
                default:
                    bootstraps.Database = new MSDatabase();
                    break;
            }
            if (!connectionString.IsNull())
                bootstraps.Database.SetDatabase(connectionString);
            bootstraps.Repository.Create(bootstraps.Database);
            return bootstraps;
        }

    }
}
